package com.jlpay.open.jlpay.sdk.java.utils;

import com.jlpay.open.jlpay.sdk.java.common.crypto.model.AnnotationData;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 注解工具类
 *
 * @author guo wei
 * @since 2022/6/17
 */
public class AnnotationUtils {
    /**
     * 获取对象下指定注解标识的所有属性（String类型）
     *
     * @param root       对象
     * @param annotation 目标注解
     * @return 注解标识的所有属性集合
     */
    public static List<AnnotationData> getAllAnnotationData(Object root, Class<? extends Annotation> annotation) {
        if (root == null) {
            return Collections.emptyList();
        }
        List<AnnotationData> annotationDataList = new ArrayList<>();
        Class<?> clazz = root.getClass();
        List<Field> fields = getAllDeclaredFields(clazz);

        for (Field field : fields) {
            ReflectionUtils.makeAccessible(field);
            Object fieldValue;
            try {
                fieldValue = field.get(root);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("访问权限异常");
            }
            if (fieldValue == null) {
                continue;
            }
            if (field.isAnnotationPresent(annotation)) {
                if (fieldValue instanceof String) {
                    String s = (String)fieldValue;
                    if (StringUtils.isNotBlank(s)) {
                        annotationDataList.add(new AnnotationData(root, field, s));
                    }
                } else if (fieldValue instanceof List) {
                    List<?> list = (List<?>)fieldValue;
                    if (CollectionUtils.isNotEmpty(list) && list.get(0) instanceof String) {
                        annotationDataList.add(new AnnotationData(root, field, fieldValue));
                    }
                } else {
                    annotationDataList.addAll(getAllAnnotationData(fieldValue, annotation));
                }
            }
        }
        return annotationDataList;
    }

    /**
     * 获取该类及其父类所有属性
     *
     * @param clazz 类
     * @return 属性列表
     */
    private static List<Field> getAllDeclaredFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        return fields;
    }
}
